import pygame
from entitymanager import*

class UserInterface(object):
    """User interface for the editor"""
    game = 0


    class Container(object):
        def __init__(self, width, height, parent = 0, surface = 0):
            
            self.parent = parent #If parent is 0, it has no parent
            self.rect = pygame.Rect(0,0,width,height) #In relation to master container
            self.containers = []
            self.items = []
            self.outsidesurface = False
            self.offset = [0,0]
            self.fill = 0

            self.actionChecks = []

            if(surface == 0):
                self.surface = pygame.Surface([width, height], pygame.SRCALPHA, 32)
                self.surface = self.surface.convert_alpha()
            else:
                self.surface = surface
                self.outsidesurface = True
            

        def mouseCheck(self, mouseCor):

            mouseInSubContainer = False

            for action in self.actionChecks:
                if(action.active == False):
                    self.actionChecks.remove(action)
                else:
                    action.run(mouseCor)
                
            mouseOffset = (mouseCor[0] - self.rect[0], mouseCor[1] - self.rect[1])
            if(len(self.items) > 0):
               for item in self.items:
                 item.actionRun(mouseOffset)

            for container in self.containers:
                inSubContainer = container.rect.collidepoint(mouseOffset)
                if(inSubContainer):
                    container.mouseCheck(mouseOffset)

                    self.containers.remove(container)#Switch container to the front
                    self.containers.insert(0, container)
                    return True

                    mouseInSubContainer = True

            return mouseInSubContainer
                
        
        def addContainer(self, container):
            self.containers.append(container)
            container.parent = self

        def addItem(self, item):
            self.items.append(item)
            item.parent = self

        def draw (self, screen, offset = (0,0)):

            if not self.outsidesurface:
                self.surface.fill((0,255,0,0))

            if(len(self.items) > 0):
               for item in self.items:
                    item.draw()

            for container in reversed(self.containers):
                if not self.outsidesurface:
                    container.draw(self.surface, self.offset)
                else:
                    container.draw(screen, self.offset)
            
            if not self.outsidesurface:
                screen.blit(self.surface, (self.rect.topleft[0] + offset[0], self.rect.topleft[1] + offset[1]))
                pass

            else:
                pass

        def resize(self):
            if(self.fill == True):
                if(self.parent != 0):
                    #self.rect.width = self.parent.rect.width
                    #self.rect.height = self.parent.rect.height
                    self.surface = pygame.Surface([self.rect.width, self.rect.height], pygame.SRCALPHA, 32)
                    self.surface = self.surface.convert_alpha()
    
    class ListContainer(Container):
        def __init__(self, width, height, setList = 0):
            
            super(UserInterface.ListContainer , self ).__init__(width, height)
            
            self.offset = [0,0]
            if(not setList == 0):
                self.setItems(setList)

        def mouseCheck(self, mouseCor):
            UserInterface.Container.mouseCheck(self, (mouseCor[0] - self.offset[0], mouseCor[1] - self.offset[1]))
            if(UserInterface.game.keysdown.get('=', False)):
                self.offset[1] += 8
            if(UserInterface.game.keysdown.get('-', False)):
                self.offset[1] -= 8

        def setItems(self, items):
            self.containers = []
            colorNum = 50

            for item in items:

                newContainer = UserInterface.Container(self.rect.width, 35)
                newContainer.rect.topleft = (0,len(self.containers) * 35)
                newContainer.addItem(UserInterface.BackgroundItem((colorNum,colorNum,colorNum)))
                
                newContainer.addItem(item)
                newContainer.parent = self
                newContainer.surface.fill((0,0,0))
                
                item.parentContainer = newContainer
                self.containers.append(newContainer)
             
        def draw(self, screen, offset = (0,0)):
            UserInterface.Container.draw(self, screen)

    class DividerContainer(Container):
        """Divides container, only vertical. Offset is height of second section"""

        def __init__(self, parent, first, second, offset):
            self.parent = parent
            width = self.parent.rect.width
            height = self.parent.rect.height
            super(UserInterface.DividerContainer , self ).__init__(width, height)

            self.addContainer(first)
            self.addContainer(second)
            
            first.rect = pygame.Rect(0,0,width, height - offset)
            second.rect = pygame.Rect(0,height - offset,width, offset)

            first.resize()
            second.resize()

       


    class Item(object):
        def __init__(self):
            self.parent = 0
            self.action = 0

        def actionRun(self, mousePos):
            if self.action != 0:
                self.action.run(mousePos)

        def draw(self):
            pass
            
    class TextItem(Item):
        def __init__(self, startText):
            super(UserInterface.TextItem , self ).__init__()
            self.text = [""]
            self.textImage = 0
            self.setText(startText)
            self.surfaceText = ""

        def setText(self,string):
            self.text[0] = string
            self.surfaceText = string
            self.textImage = UserInterface.game.defaultFont.render( self.text[0], 0, (0,0,0,0))

        def draw(self):
            if(self.text[0] != self.surfaceText):
                self.setText(self.text[0])

            self.parent.surface.blit(self.textImage, (10,10))
            pass

    class BackgroundItem(Item):
        def __init__(self, color = (0,0,0)):
            super(UserInterface.BackgroundItem , self ).__init__()
            self.color = color

        def draw(self):
            pygame.draw.rect(self.parent.surface, self.color, ( 0,0, self.parent.rect.width, self.parent.rect.height), 0)
            pass

    class Action(object):
        def __init__(self, parent, target = 0, function = 0):
            self.actions = []
            self.parent = parent
            self.active = False

        def setup(self): #Uses as an alternate constructor, saves a tiny amount of typing time. Saves less time than it took to type this.
            pass

        def run(self, mouseCor):
            for action in actions:
                action.run()


    class TestAction(Action):
        #Works only on background items or items with a color.
        
        def run(self, mouseCor):
            if pygame.mouse.get_pressed()[0]:
                self.parentItem.color = (255,0,0)
    
    class createEntityAction(Action):
        #Parent must be TextItem
        def run(self, mouseCor):
            for event in UserInterface.game.events:
                if event.type == pygame.MOUSEBUTTONDOWN:
                    newEntity = entity(UserInterface.game.entitymanager)
                    newEntity.type = self.parent.text[0]
                    newEntity.rect.topleft = (UserInterface.game.camera.rect.center[0], UserInterface.game.camera.rect.center[1])
                    newEntity.rect.width = UserInterface.game.entitymanager.textures[newEntity.type].get_width()
                    newEntity.rect.height = UserInterface.game.entitymanager.textures[newEntity.type].get_height()
                    newEntity.collides = False
                    newEntity.layer = UserInterface.game.editor.layer
                    UserInterface.game.entitymanager.addEntity(newEntity)

    class MoveAction(Action):
        def run(self, mouseCor):
            mouseMoved = pygame.mouse.get_rel() #Could mess up future calls of this function, MoveAction is using it selfishly here
            if pygame.mouse.get_pressed()[0]:
                if(self.active == False):
                    UserInterface.getParent(self).actionChecks.append(self)
                self.active = True
                self.parent.parent.rect.topleft = (self.parent.parent.rect.topleft[0] + mouseMoved[0],self.parent.parent.rect.topleft[1] + mouseMoved[1])
            else:
                self.active = False

    @staticmethod
    def getParent(object):
        if object.parent == 0:
            return object
        else:
            return UserInterface.getParent(object.parent)

class Inspector(object):

    def __init__(self, container):
        
        self.list = 0
        self.targetEntity = 0
        self.textUpdateInfo = []

        self.setupInterface(container)

    def setupInterface(self, container):
        newUIContainer = UserInterface.Container(250,250, container)
        container.addContainer(newUIContainer)

        newUIContainer.addItem(UserInterface.BackgroundItem((255,255,255)))
        newUIContainer.items[0].action = UserInterface.MoveAction(newUIContainer.items[0])

        texStrings = []

        #for tex in UserInterface.game.textures.keys():
           # newTextItem = UserInterface.TextItem(tex)
            #editAction = Inspector.EditVariableAction(newTextItem)
            #editAction.addReliant(newTextItem, newTextItem.text)
            #newTextItem.action = editAction
            #texStrings.append(newTextItem)
        
        up = UserInterface.ListContainer(newUIContainer.rect.width, newUIContainer.rect.height, texStrings)
        self.list = up
        self.changeTarget(0)
        down = UserInterface.Container(200,200)

        down.fill = True
        up.fill = True

        up.addItem(UserInterface.BackgroundItem((100,100,100)))
        down.addItem(UserInterface.BackgroundItem((0,0,0)))

        splitter = UserInterface.DividerContainer(newUIContainer, down, up, 230)
        newUIContainer.addContainer(splitter)

        self.UIContainer = newUIContainer

    def addParameter(self, objectWatching, variableChanging, textAppend, isNumber = True):
            currentValue = 0
            if(type(variableChanging) == int):
                currentValue = objectWatching[variableChanging]
            else:
                currentValue = objectWatching.__dict__[variableChanging]

            newTextItem = UserInterface.TextItem(textAppend + str(currentValue))
            editAction = Inspector.EditVariableAction(newTextItem)
            editAction.addReliant(objectWatching, variableChanging)
            editAction.floatInput = isNumber
            newTextItem.action = editAction
            
            self.textUpdateInfo.append([newTextItem, textAppend, objectWatching, variableChanging])
            return newTextItem

    def changeTarget(self, entity):
        if(entity != self.targetEntity):
            self.targetEntity = entity
            editActions = []
            if(entity != 0):
                
                editActions.append(self.addParameter(entity.rect, 0, "x: "))
                editActions.append(self.addParameter(entity.rect, 1, "y: "))
                editActions.append(self.addParameter(entity.rect, 2, "width: "))
                editActions.append(self.addParameter(entity.rect, 3, "height: "))

                editActions.append(self.addParameter(entity, "collides", "collides: ", False))
                
                if(type(entity) == trigger):
                    editActions.append(self.addParameter(entity, "trigger", "trigger: ", False))

                if(type(entity) == platform):
                    editActions.append(self.addParameter(entity, "plat", "platformable: ", False))
                    editActions.append(self.addParameter(entity, "climb", "climable: ", False))

                if(type(entity) == moveable):
                    editActions.append(self.addParameter(entity, "fetch", "fetch: ", False))
                    editActions.append(self.addParameter(entity, "chew", "chew: ", False))
                    editActions.append(self.addParameter(entity, "canbecarried", "Can be carried: ", False))
                    editActions.append(self.addParameter(entity, "mass", "mass: ", True))

                 

            #for tex in UserInterface.game.textures.keys():
               # newTextItem = UserInterface.TextItem(tex)
                #editAction = Inspector.EditVariableAction(newTextItem)#parameter is parent, not what is being edited
                #editAction.addReliant(newTextItem, newTextItem.text)#First parameter is entity being edited, second is variable or function
                #newTextItem.action = editAction
                #editActions.append(newTextItem)

            self.list.setItems(editActions)

        else:
            if(self.targetEntity != 0):
                UserInterface.game.entitymanager.removeEntity(self.targetEntity)
                UserInterface.game.entitymanager.addEntity(self.targetEntity)

            for item in self.textUpdateInfo:
                if(type(item[3]) == int):
                    item[0].setText(item[1] + str(item[2][item[3]]))
                else:
                    item[0].setText(item[1] + str(item[2].__dict__[item[3]]))


    class EditVariableAction(UserInterface.Action):
        def __init__(self, parent):
             super(Inspector.EditVariableAction , self ).__init__(parent)
             self.reliants = []
             self.floatInput = False

        def addReliant(self, reliant, variable):
            if type(variable) == list:
                self.reliants.append(variable)
                #self.reliants.append(reliant)
            else:
                self.reliants.append([variable, reliant])
                
                

        def changeEntityWidth(entity, width):
            entity.rect.width = width

        def run(self, mouseCor):
            for event in UserInterface.game.events:
                if event.type == pygame.MOUSEBUTTONDOWN:

                    reliantInfo = self.reliants[0]
                    if(type(reliantInfo[0]) == int):
                        if(type(reliantInfo[1][reliantInfo[0]]) == bool):
                            reliantInfo[1][reliantInfo[0]] = not reliantInfo[1][reliantInfo[0]]
                            return
                    else:
                        if(type(reliantInfo[1].__dict__[reliantInfo[0]]) == bool):
                            reliantInfo[1].__dict__[reliantInfo[0]] = not reliantInfo[1].__dict__[reliantInfo[0]]
                            return 

                    valueChange = raw_input("Enter a value:")
                    for reliantInfo in self.reliants:
                        if(type(reliantInfo[0]) == int):
                             if(type(reliantInfo[1][reliantInfo[0]]) == bool):
                                 reliantInfo[1][reliantInfo[0]] = not reliantInfo[1][reliantInfo[0]]
                                 return 

                             if(self.floatInput):
                           
                                    floatVal = float(valueChange)
                                    reliantInfo[1][reliantInfo[0]] = floatVal

                           
                             else:
                                    reliantInfo[1][reliantInfo[0]] = valueChange
                        else:
                            if(self.floatInput):
                           
                                    floatVal = float(valueChange)
                                    reliantInfo[1].__dict__[reliantInfo[0]] = floatVal

                           
                            else:
                                reliantInfo[1].__dict__[reliantInfo[0]] = valueChange

                        


        
    

